using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace GridSystem.Editor
{
    [CustomEditor(typeof(GridSurface))]
    public class GridSurfaceEditor : UnityEditor.Editor
    {
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            EditorGUILayout.Space();
            EditorGUILayout.HelpBox("要编辑网格，请选中此物体，然后从Unity工具栏中选择 '网格编辑器' 工具。", MessageType.Info);

            EditorGUILayout.Space();

            var surface = (GridSurface)target;

            // 检查是否存在MeshCollider
            if (!surface.TryGetComponent<MeshCollider>(out var meshCollider))
            {
                EditorGUILayout.HelpBox("为了让射线检测能精确工作，请添加一个 MeshCollider 组件。", MessageType.Warning);
                if (GUILayout.Button("添加 MeshCollider 组件"))
                {
                    surface.gameObject.AddComponent<MeshCollider>();
                }
            }
            else
            {
                // 提供更新碰撞体的按钮
                if (GUILayout.Button("根据定义好的网格更新 MeshCollider"))
                {
                    GenerateCollisionMesh(surface, meshCollider);
                }
            }
        }

        /// <summary>
        /// 为GridSurface生成一个精确匹配其定义单元格的碰撞网格。
        /// </summary>
        private void GenerateCollisionMesh(GridSurface surface, MeshCollider meshCollider)
        {
            if (surface.definedCells.Count == 0)
            {
                Debug.LogWarning("GridSurface中没有定义任何单元格，无法生成碰撞体。");
                meshCollider.sharedMesh = null;
                return;
            }

            Mesh newMesh = new Mesh();
            List<Vector3> vertices = new List<Vector3>();
            List<int> triangles = new List<int>();

            // 使用字典来合并共享的顶点，优化网格
            Dictionary<Vector3, int> vertexIndexMap = new Dictionary<Vector3, int>();

            float cellSize = surface.cellSize;
            float halfSize = cellSize * 0.5f;

            foreach (var cellPos in surface.definedCells)
            {
                // 在计算单元格中心点时，应用表面的yOffset
                Vector3 cellCenter = new Vector3(cellPos.x * cellSize, surface.yOffset, cellPos.y * cellSize);

                // 定义一个格子的四个角点（局部坐标）
                Vector3[] corners = {
                    cellCenter + new Vector3(-halfSize, 0, -halfSize), // 左下
                    cellCenter + new Vector3(halfSize, 0, -halfSize),  // 右下
                    cellCenter + new Vector3(halfSize, 0, halfSize),   // 右上
                    cellCenter + new Vector3(-halfSize, 0, halfSize)    // 左上
                };

                // 获取或创建这四个角点的顶点索引
                int v0 = GetOrAddVertex(corners[0], vertices, vertexIndexMap);
                int v1 = GetOrAddVertex(corners[1], vertices, vertexIndexMap);
                int v2 = GetOrAddVertex(corners[2], vertices, vertexIndexMap);
                int v3 = GetOrAddVertex(corners[3], vertices, vertexIndexMap);

                // 【重要修改】添加正面和背面的三角面
                // 正面 (法线朝向+Y)
                triangles.Add(v0); triangles.Add(v2); triangles.Add(v1);
                triangles.Add(v0); triangles.Add(v3); triangles.Add(v2);

                // 背面 (法线朝向-Y)
                triangles.Add(v0); triangles.Add(v1); triangles.Add(v2);
                triangles.Add(v0); triangles.Add(v2); triangles.Add(v3);
            }

            newMesh.vertices = vertices.ToArray();
            newMesh.triangles = triangles.ToArray();
            newMesh.RecalculateNormals();
            newMesh.RecalculateBounds();

            // 将生成的新网格赋给MeshCollider
            meshCollider.sharedMesh = newMesh;

            // 标记场景为已修改，以便保存
            EditorUtility.SetDirty(surface);
            Debug.Log($"成功为 {surface.name} 生成了碰撞网格！顶点数: {vertices.Count}, 三角面数: {triangles.Count / 3}", surface);
        }

        /// <summary>
        /// 辅助方法：如果顶点已存在，则返回其索引；否则，添加到列表并返回新索引。
        /// </summary>
        private int GetOrAddVertex(Vector3 vertex, List<Vector3> vertices, Dictionary<Vector3, int> map)
        {
            if (map.TryGetValue(vertex, out int index))
            {
                return index;
            }
            else
            {
                int newIndex = vertices.Count;
                vertices.Add(vertex);
                map[vertex] = newIndex;
                return newIndex;
            }
        }
    }
}